<?php
namespace Infinity;

class Query extends \SelectQuery implements \SelectQueryInterface {
  private $alias;
  private $entity_type;
  private $entity_id;
  private $bundle;
  private $conditionData;

  /**
   * @param $field
   * @param string $column
   * @param $value
   * @param string $operator
   * @return Query
   */
  public function fieldCondition($field, $column='value', $value, $operator = '='){
    $alias = $this->entity_type.'_'.$field;
    return $this->fieldLeftJoin($alias, $field)
      ->fieldConditionWithoutJoin($alias, $field, $column, $value, $operator);
  }

  /**
   * @param $alias
   * @param $field
   * @return Query
   */
  public function fieldLeftJoin($alias, $field) {
    $this->leftJoin('field_data_'.$field, $alias, '('.$alias.'.entity_id = '.$this->alias.$this->entity_id.' AND '.$alias.'.entity_type = :entity_type)',
      array(
        ':entity_type' => $this->entity_type
      )
    );
    return $this;
  }

  /**
   * @param \SelectQuery $query
   * @param $entity_type
   * @param $entity_id
   * @param $alias
   * @param $field
   * @return \SelectQuery
   */
  public static function fieldLeftJoinFromSelectQuery(\SelectQuery $query, $alias, $field, $entity_type, $entity_id)
  {
    $query->leftJoin('field_data_'.$field, $alias, '('.$alias.'.entity_id = '.$entity_id.' AND '.$alias.'.entity_type = :entity_type)',
      array(
        ':entity_type' => $entity_type
      )
    );
    return $query;
  }

  /**
   * @param $alias
   * @param $field
   * @param string $column
   * @param $value
   * @param string $operator
   * @return Query
   */
  public function fieldConditionWithoutJoin($alias, $field, $column='value', $value, $operator = '='){
    return $this->condition($alias.'.'.$field.'_'.$column, $value, $operator);
  }

  public function __set($name, $value)
  {
    if(in_array($name, array('alias', 'entity_type', 'entity_id', 'bundle')))
      $this->{$name} = $value;
  }

  /**
   * @param $key
   * @return DatabaseCondition
   */
  public function _or($key=0)
  {
    return $this->conditionManager($key, 'OR');
  }

  /**
   * @param $key
   * @param $conjunction
   * @return DatabaseCondition
   */
  public function conditionManager($key, $conjunction)
  {
    if(!isset($this->conditionData))
      $this->conditionData = array();
    if(!isset($this->conditionData[$key][$conjunction])) {
      $dc = new DatabaseCondition($conjunction);
      $dc->alias = $this->alias;
      $dc->entity_type = $this->entity_type;
      $dc->entity_id = $this->entity_id;
      $this->conditionData[$key][$conjunction] = $dc;
    }
    return $this->conditionData[$key][$conjunction];
  }

  /**
   * 确认由conditionManager追加的条件
   */
  public function conditionCommit()
  {
    if(isset($this->conditionData) && is_array($this->conditionData)) {
      foreach($this->conditionData as $condition1) {
        foreach($condition1 as $condition) {
          $this->condition($condition);
        }
      }
      $this->conditionData = array();
    }
  }

  /**
   * @param $entity_type
   * @param $alias
   * @param array $fields
   * @param $entityFields
   * @return Query
   */
  public static function select($entity_type, $alias, $fields=array(), $entityFields=array())
  {
    $bundle = '';
    $entity_info = entity_get_info($entity_type);
    $entity_id = '.'.$entity_info['entity keys']['id'];
    $query = new Query($entity_info['base table'], $alias, \Database::getConnection());
    if($entity_type == 'taxonomy_term') {
      $query->join('taxonomy_term_hierarchy', 'tth', 'tth.tid = '.$alias.'.tid');
      if(isset($fields['parent'])) {
        $query->condition('tth.parent', $fields['parent']);
        unset($fields['parent']);
      }
    }
    $query->alias = $alias;
    $query->entity_type = $entity_type;
    $query->entity_id = $entity_id;
    //$query->bundle = $bundle;
    foreach($fields as $field => $value) {
      if(is_array($value))
        $query->condition($alias.'.'.$field, $value, 'IN');
      else
        $query->condition($alias.'.'.$field, $value);
    }
    foreach($entityFields as $field => $columns) {
      $field_alias = $entity_type.'_'.$field;
      $query->fieldLeftJoin($field_alias, $field);
      foreach($columns as $column => $value) {
        $operator = '';
        $column = trim($column);
        $column_split = explode(' ', $column);
        if(count($column_split) == 2) {
          $column = $column_split[0];
          $operator = strtolower($column_split[1]);
        }
        if($operator) {
          if(is_array($value) && $operator != 'in') {
            $query->fieldConditionWithoutJoin($field_alias, $field, $column, $value[0], '>=');
            $query->fieldConditionWithoutJoin($field_alias, $field, $column, $value[1], '<=');
          } else {
            $query->fieldConditionWithoutJoin($field_alias, $field, $column, $value, $operator);
          }
        } else {
          $query->fieldConditionWithoutJoin($field_alias, $field, $column, $value);
        }
      }
    }
    return $query;
  }

  public function execute() {
    $this->conditionCommit();
    return parent::execute();
  }
}